package com.simulation.demo.service;

import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * @author buddy
 */
@Service
public class DemoService {

    /**
     * 维护进程状态
     */
    Map<String, Process> progressMap = new ConcurrentHashMap<>(16);
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3,
            10_000L, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(1024), new ThreadPoolExecutor.AbortPolicy());

    /**
     * basePath=/home/ubuntu/project/D2D3Builder/build/rundata/global/simulation3
     * python3
     * $basePath/calibrate_flow_controller.py
     * $basePath/project
     * $basePath/input/scene.csv
     * $basePath/input/materials.json
     * $basePath/RTCalibrate
     * 2
     * 2
     *
     * @param pid
     * @return
     */
    public String simulation3(Long pid) {
        // 随机生成一个sessionid
        String sessionId = pid + ":session_id:" + System.currentTimeMillis();
        // 创建项目时记录的工程目录
        String baseDir = "/home/ubuntu/project/D2D3Builder/build/rundata/global/simulation3/";
        File workDir = new File(baseDir);
        if (!workDir.exists()) {
            // 工作目录不存在
            throw new RuntimeException("工作目录不存在");
        }
        String exec = "python3";
        String cmd = baseDir + "calibrate_flow_controller.py";
        // 校正工程目录
        String projectDir = baseDir + "project";
        // 场景文件路径
        String scenePath = baseDir + "input/scene.csv";
        // materials json 路径
        String materialsPath = baseDir + "input/materials.json";
        // calibrate 文件路径
        String rtCalibrate = baseDir + "RTCalibrate";
        // 核数
        String cpus = "2";
        // 参与校正的样本百分比
        String percent = "2";
        String[] cmdArr = new String[]{exec, cmd, projectDir, scenePath, materialsPath, rtCalibrate, cpus, percent};
        try {
            threadPoolExecutor.execute(new simulation3(sessionId, workDir, cmdArr));
            // 返回sessionId 前端可以根据 session id获取状态
            return sessionId;
        } catch (Exception e) {
            // 打印错误日志
            return null;
        }
    }

    class simulation3 implements Runnable {

        String sessionId;
        File workDir;
        String[] cmdArr;

        public simulation3(String sessionId, File workDir, String[] cmdArr) {
            this.sessionId = sessionId;
            this.workDir = workDir;
            this.cmdArr = cmdArr;
        }


        @Override
        public void run() {
            /**
             * # python /path/to/calibrate_flow_controller.py /path/to/校正工程目录 /path/to/scene.csv /path/to/materials.json /path/to/calibrate_release_path 核数 参与校正的样本百分比
             */
            System.out.println(Arrays.toString(cmdArr));
            Process process;
            try {
                process = Runtime.getRuntime().exec(cmdArr, null, workDir);
                progressMap.put(sessionId, process);
                try (InputStream errorStream = process.getErrorStream()) {
                    errorConsumer.accept(errorStream);
                }
                try (InputStream inputStream = process.getInputStream()) {
                    infoConsumer.accept(inputStream);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private final Consumer<InputStream> infoConsumer = (InputStream inputStream) -> {
            try (Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
                 BufferedReader br = new BufferedReader(reader)) {
                String line;
                while ((line = br.readLine()) != null) {
                    // 记录执行日志
                    System.out.println("exec simulation3 print>info>" + sessionId + "：" + line);
                }
            } catch (IOException e) {
                // 记录错误日志
                e.printStackTrace();
            }
        };

        private final Consumer<InputStream> errorConsumer = (InputStream inputStream) -> {
            try (Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
                 BufferedReader br = new BufferedReader(reader)) {
                String line;
                while ((line = br.readLine()) != null) {
                    // 记录执行日志
                    System.out.println("exec simulation3 print>error>" + sessionId + "：" + line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        };
    }


    public String getStatus(String sessionId) {
        Process progress = progressMap.get(sessionId);
        System.out.println(progress.isAlive());
        System.out.println(progress.exitValue());
        if (progress.isAlive()) {
            return "false";
        } else {
            return progress.exitValue() + "";
        }
    }
}
